/*
* @Author:Iyoole,
* @Time  :2017-11-08
* @Description:自由组合模块
* @git   :
* */

;!function(win){
    'use strict';
    var d=document,config={
        modules:{},//模块路径
        status:{},//模块状态
        timeout:10,//超时时间(10s)
        event:{}//事件
    }
    ,fui=function () {
        this.v='1.0.0'
    }
    ,getPath=function(){
        var j=d['scripts'],jp=j[j['length']-1]['src'],sp=jp.substring(0,jp.lastIndexOf('/'));
        return sp.substring(0,sp.lastIndexOf('/') + 1);
    }()
    ,error=function(msg){
        win.console&&console.error&&console.error('fui hint: '+msg);
    }
    ,isOpera=typeof opera !=='undefined'&&opera.toString()==='[object Opera]'
    ,modules={
        JsTpl:'modules/JsTpl',//js模版
        layer:'modules/layer',//PC弹窗
        JsForm:'modules/JsForm',//表单
        JsPage:'modules/JsPage',//分页
        JsRouter:'modules/JsRouter',//路由(移动端)
        jeDate:'modules/jeDate',//时间控件
        jquery:'modules/jquery'
    };
    //记录基础数据
    fui.prototype.cache=config;
    //定义模块
    fui.prototype.define=function(d,c){
        var t=this,type=typeof d ==='function',mods=function(){
            typeof c ==='function' && c(function (app,exports) {
                fui[app]=exports;
                config.status[app]=true
            });
            return this;
        };
        type&&(c=d,d=[]);
        if(fui['fui.all']){
            return mods.call(t)
        }
        t.use(d,mods);
        return t;
    };
    //使用特定模块
    fui.prototype.use=function(apps,c,exports){
        var t=this,dir=config.dir=config.dir?config.dir:getPath,head=d.getElementsByTagName('head')[0];
        apps=typeof apps==='string'?[apps]:apps;
        //判断是否引入了jq 1.7+
        if(window.jQuery&&jQuery.fn.on){
            t.each(apps,function(i,v){
                if(v==='jquery'){
                    apps.splice(i,1);
                }
            });
            fui.jquery=fui.$=jQuery;
        }
        var item=apps[0],timeout=0,exports=exports||[];
        config.host=config.host||(dir.match(/\/\/([\s\S]+?)\//)||['//'+location.host+'/'])[0];
        //加载完毕
        function onScriptLoad(e,url) {
            var readyRegExp=navigator.platform==='PLaySTATION 3'?/^complete$/:/^(complete|loaded)$/;
            if(e.type==='load'||(readyRegExp.test((e.currentTarget||e.srcElement).readyState))){
                config.modules[item]=url;
                head.removeChild(node);
                (function poll(){
                    if(++timeout>config.timeout*1000/4){
                        return error(item+' is not valid module');
                    }
                    config.status[item]?onCallback():setTimeout(poll,4)
                })();
            }
        }
        //回调
        function onCallback(){
            exports.push(fui[item]);
            apps.length>1?t.use(apps.slice(1),c,exports):(typeof c==='function'&&c.apply(fui,exports));
        }
        //如果需要加载全部
        if(apps.length===0||(fui['fui.all']&&modules[item])){
            return onCallback(),t;
        }
        //首次加载
        if(!config.modules[item]){
            var node=d.createElement('script'),url=(modules[item]?(dir):(config.base||''))+(t.modules[item]||item)+'.js';
            node.async=true;
            node.charset='utf-8';
            node.src=url+function(){
                    var v=config.version===true?(config.v||(new Date()).getTime()):(config.version||'');
                    return v?('?v='+v):"";
                }();
            head.appendChild(node);
            if(node.attachEvent&&!(node.attachEvent.toString&&node.attachEvent.toString().indexOf('[native code]')<0)&&!isOpera){
                node.attachEvent('onreadystatechange',function(e){
                   onScriptLoad(e,url)
                });
            }else{
                node.addEventListener('load',function(e){
                    onScriptLoad(e,url)
                },false)
            }
            config.modules['item']=url;
        }else{
            (function poll(){
                if(++timeout>config.timeout*1000/4){
                    return error(item+' is not a valid module')
                }
                (typeof config.modules[item]==='string'&&config.status[item])?onCallback():setTimeout(poll,4)
            })();
        }
        return t;
    };
    //遍历
    fui.prototype.each=function(o,f){
        var key,t=this;
        if(typeof f!=='function') return t;
        o=o||[];
        if(o.constructor===Object){
            for(key in o){
                if(f.call(o[key],key,o[key])) break;
            }
        }else{
            for(key=0;key<o.length;key++){
                if(f.call(o[key],key,o[key])) break;
            }
        }
        return t;
    };
    //记录全部模块
    fui.prototype.modules = function(){
        var clone = {};
        for(var o in modules){
            clone[o] = modules[o];
        }
        return clone;
    }();
    //获取style属性值
    fui.prototype.getStyle=function(){
        var s=node.currentStyle?node.currentStyle:win.getComputedStyle(node,null);
        return s[s.getPropertyValue?'getPropertyValue':'getAttribute'](name);
    };
    //css外部加载
    fui.prototype.link=function(href,fn,cn){
        var t=this,link=d.createElement('link'),head=d.getElementsByTagName('head')[0];
        if(typeof fn==='string') cn=fn;
        var app=(cn||href).replace(/\.|\//g,''),timeout=0;
        link.rel='stylesheet';
        link.href=href+(config.debug?'v='+new Date().getTime():'');
        link.media='all';
        if(!d.getElementById(id)){
            head.appendChild(link);
        }
        if(typeof fn !== 'function') return t;
        //轮询css是否加载完毕
        (function poll() {
            if(++timeout > config.timeout * 1000 / 100){
                return error(href + ' timeout');
            }
            parseInt(t.getStyle(d.getElementById(id), 'width')) === 1989 ? function(){
                fn();
            }() : setTimeout(poll, 100);
        }());

        return t;
    };
    //css内部加载
    fui.prototype.addCss=function(n,fn,cn){
        return fui.link(config.dir+'css/'+n,fn,cn);
    };
    //图片预加载
    fui.prototype.img=function (url,c,error) {
        var img=new Image();
        img.src=url;
        if(img.complete){
            return c(img)
        }
        img.onload=function () {
            img.onload=null;
            c(img)
        };
        img.onerror=function (e) {
            img.onerror=null;
            error(e)
        }
    };
    //全局配置
    fui.prototype.config=function (opts) {
        opts=opts||{};
        for(var k in opts){
            config[k]=opts[k]
        }
        return this;
    };
    //拓展模块
    fui.prototype.extend=function(opts){
        var t=this;
        opts=opts||{};
        for(var o in opts){
            if(t[o]||t.modules[o]){
                error('\u6A21\u5757\u540D '+ o +' \u5DF2\u88AB\u5360\u7528')
            }else{
                t.modules[o]=opts[o]
            }
        }
        return t;
    };
    //本地存储
    fui.prototype.data=function (table,settings) {
        table=table||'fui';
        if(!win.JSON||!win.JSON.parse) return;
        if(settings===null){
            return delete localStorage[table]
        }
        settings=typeof settings ==='object'?settings:{key:settings};
        try{
            var data=JSON.parse(localStorage[table])
        }catch(e){
            var data={}
        }
        if(settings.value) data[settings.key]=settings.value;
        if(settings.remove) delete data[settings.key];
        localStorage[table]=JSON.stringify(data);
        return settings.key?data[settings.key]:data
    };
    //设备信息
    fui.prototype.device=function(){
        var agent=navigator.userAgent.toLowerCase(),getVersion=function(lb){
            var exp=new RegExp(lb+'/([^\\s\\_\\-]+)');
            lb=(agent.match(exp)||[])[1];
            return lb || false
        },result={
            os:function(){
                if(/windows/.test(agent)){
                    return 'window'
                }else if(/linux/.test(agent)){
                    return 'linux'
                }else if(/iphone|ipod|ipad|ios/.test(agent)){
                    return 'ios'
                }else if(/mac/.test(agent)){
                    return 'mac'
                }
            }(),ie:function(){
                return (!!win.ActiveXObject||"ActiveXObject" in win)?(
                    (agent.match(/msie\s(\d+)/)||[])[1]||'11'
                ):false
            }(),weixin:getVersion('micromessenger')
        };
        if(key && !result[key]){
            result[key]=getVersion(key)
        }
        result.android=/android/.test(agent);
        result.ios=result.os==='ios';
        return result
    };
    //阻止冒泡事件
    fui.prototype.stope=function(e){
        e=e||win.event;
        e.stopPropagation()?e.stopPropagation():e.cancelBubble=true
    };
    //自定义模块事件
    fui.prototype.onevent=function(modName,events,c){
        if(typeof modName !== 'string'
            || typeof callback !== 'function') return this;
        config.event[modName + '.' + events] = [c];
        return this
    };
    //执行算定义事件
    fui.prototype.event=function (modName,events,params) {
        var t = this
            ,result = null
            ,filter = events.match(/\(.*\)$/)||[] //提取事件过滤器
            ,set = (events = modName + '.'+ events).replace(filter, '') //获取事件本体名
            ,callback = function(_, item){
            var res = item && item.call(t, params);
            res === false && result === null && (result = false);
        };
        t.each(config.event[set], callback);
        filter[0] && t.each(config.event[events], callback); //执行过滤器中的事件
        return result;
    };
    //路由
    var c={
        gu:function(){
            var h = location.hash.split("?"),
                n = h[0].split("#")[1],//路由地址
                p = h[1] ? h[1].split("&") : [],//参数内容
                q = {};
            for(var x = 0;x<p.length ; x++){
                var m = p[x].split("=");
                q[m[0]] = m[1]
            }
            return  {
                path:n,
                query:q
            }
        },
        isFun:function(o){
            return Object.prototype.toString.call(o)==='[object Function]'
        },
        isArr:function(o){
            return Object.prototype.toString.call(o)==='[object Array]'
        }
    };
    var router=function(){
        this.rs={};//用来存放注册路由
        this.way=[];//用于记录hash
    };
    router.pt=router.prototype;
    router.pt.render=function(){
        var t=this;
        window.addEventListener('load',function(){
            t.load()
        });
        window.addEventListener('hashchange',function(){
            t.change()
        });
    };
    router.pt.map=function(opts){//注册路由
        if(c.isArr(opts)){
            var t=this;
            for(var x=0;x<opts.length;x++){
                var path=opts[x]['path'].replace(/\s*/g,'');
                t.rs[path]={
                    path:opts[x].path||"",
                    template:opts[x].template||"",
                    join:opts[x].join||"",
                    back:opts[x].back||"",
                    async:opts[x].async||""
                };
                opts[x]['async']?t.rs[path]['fn']=-1:'';
            }
        }else{
            console.trace('路由配置不对')
        }
    };
    router.pt.load=function(){
        var nh=c.gu();
        if(this.rs[nh.path]){
            this.way=[nh.path];
            this.refresh(nh)
        }else{
            location.hash='/index'
        }
    };
    router.pt.change=function(){
        var nh=c.gu(),t=this;
        if(t.rs[nh.path]){
            if(t.way[t.way.length-1]==nh.path){
                t.call(1,nh)
            }else{
                if(t.way.length>1&&t.way[t.way.length-2]==nh.path){
                    t.exit(nh);
                    t.refresh(nh,2)
                }else{
                    t.join(nh.path);
                    t.refresh(nh,1)
                }
            }
        }
    };
    router.pt.join=function(p){//加入
        var t=this;
        t.way.push(p);
    };
    router.pt.exit=function(){//退出
        var t=this;
        t.way.pop();
    };
    router.pt.call=function(type,nh){
        var t=this;
        if(type==1){
            var join;
            try{
                join=eval(t.rs[nh.path]['join']);
                join(nh['query']);
            }catch (e){}
        }else{
            var back;
            try{
                back=eval(t.rs[nh.path]['back']);
                back(nh['query']);
            }catch (e){}
        }
    };
    router.pt.refresh=function(nh,type){
        var t=this;
        type=type||1;
        if(t.rs[nh.path].fn==-1){
            var _b=document.getElementsByTagName('body')[0];
            var _s=document.createElement('script');
            _s.type='text/javascript';
            _s.src=t.rs[nh.path]['async'];
            _s.async=true;
            _s.onload=function(){
                t.rs[nh.path].fn=1;
                t.call(type,nh)
            };
            _b.appendChild(_s)
        }else{
            t.call(type,nh)
        }
    };
    win.JsRouter=new router();
    win.fui=new fui();
}(window);







